package perceptronMathieu;

import perceptronMathieu.function.IFunction;
import perceptronMathieu.function.XOR;


public class SAES
{
	public GaussianRandom	g	= new GaussianRandom();

	public static class Range
	{
		protected double	min;
		protected double	max;

		public Range(double min, double max)
		{
			if (min < max)
			{
				this.min = min;
				this.max = max;
			} else
			{
				this.min = max;
				this.max = min;
			}
		}
	}

	public void run(IFunction function, double rangeSize, int iterationLimit)
	{
		double xParent[] = new double[function.getDimension()];
		double xChild[] = new double[function.getDimension()];

		Range range = new Range(rangeSize * (-1), rangeSize);
		double sigma = (range.max - range.min) / 3.0;

		xParent = getInitialParent(range, function.getDimension());

		for (int i = 0; i < iterationLimit; ++i)
		{
			System.out.println(sigma + ";\t" + function.fitness(xParent));
			xChild = getCandidate(xParent, sigma);
			if (function.fitness(xChild) <= function.fitness(xParent))
			{
				for (int k = 0; k != xParent.length; k++)
				{
					xParent[k] = xChild[k];
				}
				sigma = 2 * sigma;
			} else
			{
				sigma = Math.pow(2, -0.25) * sigma;
				if (sigma < Math.pow(10, -8))
				{
					sigma = Math.pow(10, -8);
				}
			}
		}
	}

	private double[] getInitialParent(Range range, int dimension)
	{
		double xParent[] = new double[dimension];
		for (int i = 0; i < xParent.length; ++i)
		{
			xParent[i] = range.max * g.random() - (range.max - range.min) / 2;
		}
		return xParent;
	}

	public double[] getCandidate(double xParent[], double sigma)
	{
		double xCandidate[] = new double[xParent.length];

		for (int i = 0; i < xParent.length; ++i)
		{
			xCandidate[i] = xParent[i] + sigma * g.random();
		}
		return xCandidate;
	}

	public String vectorToString(double x[])
	{
		String print = "";
		for (int i = 0; i < x.length; ++i)
		{
			print += " , " + x[i];
		}
		return print;
	}

	public static void main(String[] args)
	{
		SAES algo = new SAES();

		XOR perceptron = new XOR();
		algo.run(perceptron, 1, 2000);

		if (!perceptron.test(true, true))
		{
			System.out.println(perceptron);
		}
		if (!perceptron.test(true, false))
		{
			System.out.println(perceptron);
		}
		if (!perceptron.test(false, true))
		{
			System.out.println(perceptron);
		}
		if (!perceptron.test(false, false))
		{
			System.out.println(perceptron);
		}

		
//		IFunction function = new Sphere(100); 
//		
//		algo.run(function, 10, 10000);
		 
	}
}
